package com.ll.dao;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.ll.exception.UserException;
import com.ll.exception.UserExceptionConstants;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;

import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.result.UpdateResult;
import com.ll.utils.BsonUtil;

/**
 * Mongodb连接
 */
public class MongoManager {

	private static Logger log = Logger.getLogger(MongoManager.class.getName());

	private static final MongoManager instance = new MongoManager();

	private static MongoClient mongoClient = null;

	private static int port;

	private static String host;

	private static String dbName;

	/**
	 * 私有化
	 */
	private MongoManager() {
	}

	/**
	 * 单例
	 * 
	 * @return
	 */
	public static MongoManager getInstance() {

		return instance;

	}

	/*
	 * 获取端口，ip
	 */

	/**
	 * 初始化MongoDB
	 * 
	 * @throws IOException
	 */
	public void init() {
		try {
			Properties properties = new Properties();
			InputStream filePath = MongoManager.class.getClassLoader().getResourceAsStream("mongodb.properties");
			properties.load(filePath);
			host = (String) properties.get("host");
			port = Integer.valueOf((String) properties.get("port"));
			dbName = (String) properties.get("dbName");
			mongoClient = new MongoClient(host, port);
			log.info("MongoDB init success!");
		} catch (IOException e) {
			throw new UserException(UserExceptionConstants.IO_ERROR);
		}

	}

	/**
	 * 获取DB对象
	 * 
	 * @return
	 * @throws IOException
	 */
	public MongoDatabase getDB() {
		try {
			if (mongoClient == null) {
				init();
				log.log(Level.INFO, "Get DB : local");
			}
			return mongoClient.getDatabase(dbName);

		} catch (Exception e) {
			throw new UserException(UserExceptionConstants.GET_ERROR);
		}
	}

	/**
	 * 插入MongoDB
	 * 
	 * @throws IOException
	 */
	public void insert(Object object) {

		String name = object.getClass().getName();
		int indexOf = name.lastIndexOf(".");
		String tablename = name.substring((indexOf + 1), name.length());

		// 获取集合
		MongoCollection<Document> collection = getDB().getCollection(tablename);

		// 将传入的对象转换成bson格式
		Document document = null;
		try {
			document = BsonUtil.toBson(object);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
		// 插入数据
		collection.insertOne(document);
	}

	/**
	 * 关闭Mongo链接
	 */
	public void close() {
		try {
			if (mongoClient != null) {
				mongoClient.close();
				log.info("MongoClient has benn closed...");
			}
		} catch (Exception e) {
			throw new UserException(UserExceptionConstants.CLOSE_ERROR);
		}
	}

	/**
	 * 获取一张表中的所有链接
	 * 
	 * @param tablename
	 *            表名
	 * @return
	 */
	public List<String> selectList(String tablename) {
		MongoCollection<Document> collection = getDB().getCollection(tablename);
		MongoCursor<Document> cursor = collection.find().iterator();
		List<String> urlList = new ArrayList<String>();
		while (cursor.hasNext()) {
			String pageUrl = (cursor.next().get("url") + "").trim();
			urlList.add(pageUrl);
		}
		return urlList;
	}

	/**
	 * 查询
	 * 
	 * @param tablename
	 *            表名
	 * @param filter
	 *            条件
	 * @return
	 */
	public MongoCursor<Document> query(String tablename, Bson filter) {
		MongoCollection<Document> collection = getDB().getCollection(tablename);
		if (filter == null) {
			filter = new Document();
		}
		return collection.find(filter).iterator();
	}

	/**
	 * 更新
	 * 
	 * @param tablename
	 *            表名
	 * @param filter
	 *            条件
	 * @param update
	 *            更新值
	 * @return
	 */
	public long update(String tablename, Bson filter, Bson update) {
		if (filter == null || update == null) {
			throw new UserException(UserExceptionConstants.PARAMETER_ERROR);
		}
		MongoCollection<Document> collection = getDB().getCollection(tablename);
		UpdateResult updateMany = collection.updateMany(filter, update);
		return updateMany.getModifiedCount();
	}

	
	/**
	 * 分组
	 * @param tablename
	 * @return
	 */
	public AggregateIterable<Document> group(String tablename,List<? extends Bson> pipeline) {
		MongoCollection<Document> collection = getDB().getCollection(tablename);
		return collection.aggregate(pipeline);
	}

	
	public static void main(String[] args) {
		// 查询
		// Document filter = new Document();
		// filter.put("hgvs", "NM_000135.2:c.1340C>T ");
		// MongoCursor<Document> cursor =
		// MongoManager.getInstance().query("ClinVarSet", null);
		// while (cursor.hasNext()) {
		// System.out.println(cursor.next().get("condition"));
		// }
		// 修改
		Document filter = new Document();
		filter.put("_id", new ObjectId("581028085cb2e26f7c065c22"));
		Document update = new Document();
		// update.put("source", "1");
		BasicDBObject update1 = new BasicDBObject("$set", update);
		System.out.println(MongoManager.getInstance().update("wegenenew", filter, null));
		;
	}
}